"""
缓存管理器 - 减少跨地域数据库查询
用于香港服务器缓存国内数据库的数据
"""

import json
import asyncio
from typing import Any, Optional, Dict, List
from datetime import datetime, timedelta
import redis.asyncio as aioredis
from app.config import settings
from app.utils.logger import get_monitor_logger

logger = get_monitor_logger()

class CacheManager:
    """缓存管理器 - 专为跨地域部署优化"""
    
    def __init__(self):
        self.redis_client = None
        self.default_ttl = 300  # 默认5分钟缓存
        
    async def get_redis_client(self):
        """获取Redis客户端"""
        if not self.redis_client:
            self.redis_client = aioredis.from_url(
                settings.REDIS_URL,
                decode_responses=True,
                socket_connect_timeout=5,
                socket_timeout=5,
                retry_on_timeout=True,
                health_check_interval=30
            )
        return self.redis_client
    
    async def get_cached_data(self, key: str) -> Optional[Any]:
        """获取缓存数据"""
        try:
            redis = await self.get_redis_client()
            cached_data = await redis.get(key)
            
            if cached_data:
                return json.loads(cached_data)
            return None
            
        except Exception as e:
            logger.error(f"❌ 获取缓存失败 {key}: {e}")
            return None
    
    async def set_cached_data(self, key: str, data: Any, ttl: int = None) -> bool:
        """设置缓存数据"""
        try:
            redis = await self.get_redis_client()
            ttl = ttl or self.default_ttl
            
            serialized_data = json.dumps(data, default=str, ensure_ascii=False)
            await redis.setex(key, ttl, serialized_data)
            
            return True
            
        except Exception as e:
            logger.error(f"❌ 设置缓存失败 {key}: {e}")
            return False
    
    async def delete_cached_data(self, key: str) -> bool:
        """删除缓存数据"""
        try:
            redis = await self.get_redis_client()
            await redis.delete(key)
            return True
            
        except Exception as e:
            logger.error(f"❌ 删除缓存失败 {key}: {e}")
            return False
    
    # 监控相关缓存方法
    async def get_cached_monitors(self, user_id: int) -> Optional[List[Dict]]:
        """获取用户监控任务缓存"""
        key = f"user_monitors:{user_id}"
        return await self.get_cached_data(key)
    
    async def set_cached_monitors(self, user_id: int, monitors: List[Dict], ttl: int = 600) -> bool:
        """缓存用户监控任务（10分钟）"""
        key = f"user_monitors:{user_id}"
        return await self.set_cached_data(key, monitors, ttl)
    
    async def get_cached_monitor(self, monitor_id: int) -> Optional[Dict]:
        """获取单个监控任务缓存"""
        key = f"monitor:{monitor_id}"
        return await self.get_cached_data(key)
    
    async def set_cached_monitor(self, monitor_id: int, monitor_data: Dict, ttl: int = 300) -> bool:
        """缓存单个监控任务（5分钟）"""
        key = f"monitor:{monitor_id}"
        return await self.set_cached_data(key, monitor_data, ttl)
    
    async def invalidate_user_cache(self, user_id: int):
        """清除用户相关缓存"""
        keys_to_delete = [
            f"user_monitors:{user_id}",
            f"user_profile:{user_id}",
            f"user_settings:{user_id}"
        ]
        
        for key in keys_to_delete:
            await self.delete_cached_data(key)
    
    # 商品数据缓存
    async def get_cached_products(self, keyword: str) -> Optional[List[Dict]]:
        """获取商品搜索结果缓存"""
        key = f"products:{keyword}"
        return await self.get_cached_data(key)
    
    async def set_cached_products(self, keyword: str, products: List[Dict], ttl: int = 180) -> bool:
        """缓存商品搜索结果（3分钟）"""
        key = f"products:{keyword}"
        return await self.set_cached_data(key, products, ttl)
    
    # 用户数据缓存
    async def get_cached_user(self, user_id: int) -> Optional[Dict]:
        """获取用户信息缓存"""
        key = f"user_profile:{user_id}"
        return await self.get_cached_data(key)
    
    async def set_cached_user(self, user_id: int, user_data: Dict, ttl: int = 1800) -> bool:
        """缓存用户信息（30分钟）"""
        key = f"user_profile:{user_id}"
        return await self.set_cached_data(key, user_data, ttl)
    
    # 批量操作缓存
    async def get_multiple_cached_data(self, keys: List[str]) -> Dict[str, Any]:
        """批量获取缓存数据"""
        try:
            redis = await self.get_redis_client()
            cached_values = await redis.mget(keys)
            
            result = {}
            for key, value in zip(keys, cached_values):
                if value:
                    try:
                        result[key] = json.loads(value)
                    except json.JSONDecodeError:
                        result[key] = None
                else:
                    result[key] = None
            
            return result
            
        except Exception as e:
            logger.error(f"❌ 批量获取缓存失败: {e}")
            return {key: None for key in keys}
    
    async def set_multiple_cached_data(self, data_dict: Dict[str, Any], ttl: int = None) -> bool:
        """批量设置缓存数据"""
        try:
            redis = await self.get_redis_client()
            ttl = ttl or self.default_ttl
            
            pipe = redis.pipeline()
            for key, data in data_dict.items():
                serialized_data = json.dumps(data, default=str, ensure_ascii=False)
                pipe.setex(key, ttl, serialized_data)
            
            await pipe.execute()
            return True
            
        except Exception as e:
            logger.error(f"❌ 批量设置缓存失败: {e}")
            return False
    
    # 缓存统计
    async def get_cache_stats(self) -> Dict[str, Any]:
        """获取缓存统计信息"""
        try:
            redis = await self.get_redis_client()
            info = await redis.info()
            
            return {
                "used_memory": info.get("used_memory_human", "N/A"),
                "connected_clients": info.get("connected_clients", 0),
                "total_commands_processed": info.get("total_commands_processed", 0),
                "keyspace_hits": info.get("keyspace_hits", 0),
                "keyspace_misses": info.get("keyspace_misses", 0),
                "hit_rate": round(
                    info.get("keyspace_hits", 0) / 
                    max(info.get("keyspace_hits", 0) + info.get("keyspace_misses", 0), 1) * 100, 2
                )
            }
            
        except Exception as e:
            logger.error(f"❌ 获取缓存统计失败: {e}")
            return {}

# 全局缓存管理器实例
cache_manager = CacheManager()

# 缓存装饰器
def cache_result(ttl: int = 300, key_prefix: str = ""):
    """缓存函数结果的装饰器"""
    def decorator(func):
        async def wrapper(*args, **kwargs):
            # 生成缓存key
            cache_key = f"{key_prefix}:{func.__name__}:{hash(str(args) + str(kwargs))}"
            
            # 尝试从缓存获取
            cached_result = await cache_manager.get_cached_data(cache_key)
            if cached_result is not None:
                logger.debug(f"🎯 缓存命中: {cache_key}")
                return cached_result
            
            # 执行函数并缓存结果
            result = await func(*args, **kwargs)
            if result is not None:
                await cache_manager.set_cached_data(cache_key, result, ttl)
                logger.debug(f"💾 缓存设置: {cache_key}")
            
            return result
        return wrapper
    return decorator
